using System;
using System.Collections.Generic;
using System.Text;
using EPiSugar.Content;
using System.Web.UI.HtmlControls;
using System.Web.UI;

namespace EPiSugar.Markup
{
    /// <summary>
    /// A lightweight tag builder. Can output html tags with attributes and 
    /// content as string or as a asp.net web control. A notable distinction
    /// from traditional asp.net web controls is that the tag builder will 
    /// return a null string if it contains no content.
    /// </summary>
    public class Tag
    {
        public static implicit operator string(Tag tag)
        {
            if (tag == null)
                return null;
            return tag.ToString();
        }

        public Tag(string tag, string innerHtml, params KeyValuePair<string,string>[] attributes)
            : this(tag, innerHtml)
        {
            foreach (var attribute in attributes)
                Attributes[attribute.Key] = attribute.Value;
        }

        public Tag(string tagName, string innerHtml)
            : this(tagName)
        {
            InnerHtml = innerHtml;
        }

        public Tag(string tagName)
        {
            Name = tagName;
            Attributes = new Dictionary<string, string>();
            RenderCondition = delegate { return InnerHtml != null; };
        }

        public string Name { get; set; }
        public IDictionary<string, string> Attributes { get; protected set; }
        public string InnerHtml { get; set; }
        public Func<bool> RenderCondition;

        public Tag Attr(string key, string value)
        {
            if (!key.HasValue()) throw new ArgumentException("Key is null or empty.", "key");

            Attributes[key] = value;
            
            return this;
        }

        public Tag Id(string id)
        {
            Attributes["id"] = id;
            return this;
        }

        public Tag Class(string className)
        {
            Attributes["class"] = className;
            return this;
        }

        public Tag AddClass(string className)
        {
            if (Attributes.ContainsKey("class"))
                className = Attributes["class"] + " " + className;
            return Class(className);
        }

        public Tag RenderWhen(Func<bool> shouldRender)
        {
            RenderCondition = shouldRender;
            return this;
        }

        public virtual Control ToControl()
        {
            if (RenderCondition != null && !RenderCondition())
                return null;

            HtmlGenericControl c = new HtmlGenericControl(Name);
            foreach (var attribute in Attributes)
                c.Attributes[attribute.Key] = attribute.Value;
            c.InnerHtml = InnerHtml;
            return c;
        }

        public override string ToString()
        {
            if (RenderCondition != null && !RenderCondition())
                return null;

            StringBuilder markup = new StringBuilder("<" + Name);

            foreach (KeyValuePair<string, string> attribute in Attributes)
            {
                if (attribute.Value.HasValue())
                {
                    markup.AppendFormat(" {0}=\"{1}\"", attribute.Key, attribute.Value);
                }
            }

            if (string.IsNullOrEmpty(InnerHtml))
            {
                markup.Append("/>");
            }
            else
            {
                markup.Append(">").Append(InnerHtml).AppendFormat("</{0}>", Name);
            }

            return markup.ToString();
        }
    }
}
